home *** CD-ROM | disk | FTP | other *** search
/ No Fragments Archive 12: Textmags & Docs / nf_archive_12.iso / MAGS / SOURCES / ATARI_SRC.ZIP / atari source / AHDI / TTDRIVER / 4.02 / SCSI.S < prev    next >
Encoding:
Text File  |  2001-02-09  |  17.7 KB  |  673 lines

  1. ;+
  2. ; Edit History
  3. ;
  4. ; May-17-89    ml.    Started this with jwt's SCSI code.
  5. ; Aug-21-89    ml.    Added format code.
  6. ; Nov-17-89    ml.    Only add 8 to byte count on DMA reads, not writes.
  7. ; Dec-04-89    ml.    Always hand-shake last 8 bytes of data when writing
  8. ;            to disk because of hardware counter handling.
  9. ;            Added w4cntout().
  10. ;            (refer to comments at _wrtscsi())
  11. ; Jan-23-90    ml.    Undid modifications done on Dec-04-89.
  12. ;            (refer to comments at _wrtscsi())
  13. ; Jul-31-90    ml.    Modified to handle vectored-interrupts in addition
  14. ;            to polling.
  15. ;-
  16.  
  17.  
  18. .include    "defs.h"
  19. .include    "sysvar.h"
  20. .include    "scsi.h"
  21. .include    "68030.s"
  22.  
  23. ;+
  24. ; Command length
  25. ;-
  26. NCMD    equ    6        ; length of short command (in bytes)
  27.  
  28.  
  29. .if    VI            ; if vectored-interrupts desired
  30. dmac_int:    dc.b    0    ; flag for DMAC interrupts
  31. phase_changed:    dc.b    0    ; flag for SCSI phase changes
  32. .endif    ;VI
  33.  
  34.  
  35. .if    !DRIVER            ; not to be included in driver
  36. scxltmout:    dc.l    12001    ; SCSI extra long-timeout (>= 1 min)
  37. slwsclto:    dc.l    5000    ; SCSI long-timeout (25 S) for stunit()
  38. slwscsto:    dc.l    42    ; SCSI short-timeout (205 mS) for stunit()
  39. scltmout:    dc.l    201    ; SCSI long-timeout (at least 1000 ms)
  40. scstmout:    dc.l    101    ; SCSI short-timeout (at least 500 ms)
  41. .even
  42. .endif    ;!DRIVER
  43.  
  44.  
  45. ;+
  46. ; smplscsi() - send a simple SCSI command (ie. no DMA involved)
  47. ;
  48. ;    d0.w = physical unit number
  49. ;    d1.l = transfer length (in bytes)
  50. ;    d2.w = command length (NCMD or LCMD)
  51. ;    a0.l = buffer address
  52. ;-
  53.     .globl    _smplscsi
  54. _smplscsi:
  55.     andi.w    #7,d0            ; mask off the flags to get unit num
  56.     bsr    sblkscsi        ; send command block
  57.     bpl.s    .0            ; if successful, wait for status
  58.     rts                ; else return
  59. .0:    bra    w4stat            ; waiting for status byte
  60.  
  61.  
  62. ;+
  63. ; rcvscsi() - send a SCSI command which receives data back.
  64. ;
  65. ; Passed:
  66. ;    d0.w = physical unit number
  67. ;    d1.l = transfer length (in bytes)
  68. ;    d2.w = command length (NCMD or LCMD)
  69. ;    a0.l = buffer address
  70. ;
  71. ; Comments:
  72. ;    The code that checks whether there is data left in the residue
  73. ; register does not work for some transfers of less than 4 bytes to a
  74. ; non-longword aligned address.  
  75. ;-
  76.     .globl    _rcvscsi
  77. _rcvscsi:
  78. .if    !SCDMA                ; if not doing DMA
  79.     move.l    a0,-(sp)        ; save buffer address
  80. .endif    ;SCDMA
  81.     andi.w    #7,d0            ; mask off the flags to get unit num
  82.  
  83. .if    SCDMA                ; if doing DMA
  84. .if    ODMA                ; and using Old DMA controller
  85.     addq.l    #8,d1            ; add 8 because of hardware bug
  86. .endif    ;ODMA
  87. .endif    ;SCDMA
  88.  
  89.     move.w    d2,-(sp)        ; save the command length
  90.     bsr    sblkscsi        ; send command block
  91.     move.w    (sp)+,d2        ; restore the command length
  92. .if    !SCDMA                ; if not doing DMA
  93.     move.l    (sp)+,a0        ; restore buffer address
  94. .endif    ;SCDMA
  95.     tst.w    d0            ; successful?
  96.     bmi    rsend            ; if not successful, return
  97.  
  98.     move.b    #0,SCSIICR        ; deassert the data bus
  99.     move.b    #1,SCSITCR        ; set data in phase
  100.     move.b    SCSIREI,d0        ; clear potential interrupt
  101.  
  102. .if    SCDMA
  103.                     ; Set up the DMAC for data transfer
  104.     move.b    #2,SCSIMR        ; enable DMA mode
  105.     move.b    #0,SCSIDIR        ; start the DMA receive
  106.     move.w    #DMAIN,SDMACTL        ; set the DMAC direction to IN
  107.     move.w    #DMAIN+DMAENA,SDMACTL    ; turn on DMAC
  108.  
  109.     bsr    setscstmout        ; set up a short timeout
  110.     cmpi.w    #NCMD,d2        ; is this a long command?
  111.     beq.s    .0            ; if not, just go on
  112.     bsr    setscxltmout        ; else, set up an extra long timeout
  113. .0:    bsr    w4int            ; wait for interrupts
  114.     tst.w    d0            ; successful?
  115.     bne.s    rsend            ; if error, returns
  116.     bsr    w4stat            ; wait for status byte
  117.     tst.w    d0            ; successful?
  118.     bne.s    rsend            ; if error, returns
  119.     move.l    d0,-(sp)        ; else save returned status
  120.  
  121.     move    sr,-(sp)        ; go to IPL 7
  122.     ori    #$700,sr        ; no interrupts right now kudasai
  123.     movecacrd0            ; d0 = (cache control register)
  124.     ori.w    #$808,d0        ; dump both the D and I cache
  125.     moved0cacr            ; update cache control register
  126.     move    (sp)+,sr        ; restore interrupt state
  127.  
  128.     move.b    bSDMAPTR+6,d0        ; see if this was an odd transfer
  129.     andi.w    #3,d0            ; (ie, not multiple of 4)
  130.     beq.s    .2            ; no, nice and even (and easy)
  131.  
  132.     movea.l    #bSDMAPTR,a1        ; a1 -> DMA address
  133.     movep.l    (0,a1),d0        ; d0 = current value of DMA pointer
  134.     move.l    d0,d1            ; d1 = current value of DMA pointer
  135.  
  136.     andi.w    #3,d0            ; # bytes left in residue register
  137.     andi.w    #$FFFF-3,d1        ; where does data go to?
  138.     movea.l    d1,a0            ; a0 -> where rest of data should go
  139.     move.l    SDMARES,d1        ; get the residue
  140.     subq.w    #1,d0            ; dbra likes one less than count
  141. .1:    rol.l    #8,d1            ; tranfer residue to buffer
  142.     move.b    d1,(a0)+
  143.     dbra    d0,.1
  144.  
  145. .2:    move.l    (sp)+,d0        ; recall the status byte
  146.  
  147. .else    ;SCDMA
  148.     movea.l    a0,a1            ; a1 -> buffer to read into
  149.     movea.l    #bSCSI,a2        ; a2 -> 5380
  150. .3:    bsr    setscstmout
  151.     bsr    w4req            ; wait for REQ to come
  152.     bmi.s    rsend            ; if timed out, returns
  153.     btst    #3,5*REGSTEP(a2)    ; still in data in phase?
  154.     beq    w4stat            ; no, go get status
  155.     move.b    (a2),(a1)+        ; read the data byte
  156.     bsr    doack
  157.     bra.s    .3            ; do next byte
  158. .endif    ;SCDMA
  159. rsend:    rts
  160.  
  161.  
  162. ;+
  163. ; wrtscsi() - send a SCSI command which will write data to the target
  164. ;
  165. ; Passed:
  166. ;    d0.w = physical unit number
  167. ;    d1.l = transfer length (in bytes)
  168. ;    d2.w = command length (NCMD or LCMD)
  169. ;    a0.l = buffer address
  170. ;
  171. ; Comments: 
  172. ; 12/04/89 ml
  173. ;    Bus error occurs when doing a write to the disk that ends at top
  174. ; of memory.  The DMA counter is decremented when the bytes are written 
  175. ; from the ping pong buffers to the device, not when bytes are grapped 
  176. ; from RAM to the ping pong buffers.  Well, AFTER the last 8 bytes are 
  177. ; read into the ping pong buffers and BEFORE they are written to the 
  178. ; device, the chip will attempt to read the NEXT 8 bytes into the ping 
  179. ; pong buffers which results in a bus error because it will be reading 
  180. ; pass top of memory.  To get around this HARDWARE BUG, the code will 
  181. ; ALWAYS handshake the last 8 bytes over instead of DMAing them.
  182. ;
  183. ; 01/23/90 ml
  184. ;    A. Pratt said he's willing to move the screen down and sacrifice
  185. ; 16 bytes of memory.  So, code added on 12/04/89 is commented out.
  186. ;-
  187.     .globl    _wrtscsi
  188. _wrtscsi:
  189.     andi.w    #7,d0            ; mask off the flags to get unit num
  190.  
  191. .if    !SCDMA
  192.     move.l    a0,-(sp)        ; save beginning buffer address
  193. .endif    ;!SCDMA
  194.  
  195. .0:    move.w    d2,-(sp)        ; save command length
  196.     bsr    sblkscsi        ; send command block
  197.     move.w    (sp)+,d2        ; restore command length
  198. .if    !SCDMA
  199.     move.l    (sp)+,a0        ; a0 = where DMA ends
  200. .endif    ;!SCDMA
  201.     tst.w    d0            ; successful?
  202.     bpl.s    .1            ; if successful, go on
  203.     rts                ; else return
  204.  
  205. .1:    move.b    #0,SCSITCR        ; set data out phase
  206.     move.b    SCSIREI,d0        ; clear potential interrupt
  207.  
  208. .if    SCDMA
  209.                     ; Set up the DMAC for data transfer
  210.     move.b    #2,SCSIMR        ; enable DMA mode
  211.     move.b    #0,SCSIDS        ; start the DMA send
  212.     move.w    #DMAOUT,SDMACTL        ; set the DMAC direction
  213.     move.w    #DMAOUT+DMAENA,SDMACTL    ; turn on DMAC
  214.  
  215.     bsr    setscstmout        ; set up a short timeout
  216.     cmpi.w    #NCMD,d2        ; is this a long command?
  217.     beq.s    .2            ; if not, just go on
  218.     bsr    setscxltmout        ; set up an extra long timeout
  219. .2:    bsr    w4int            ; wait for interrupts
  220.     tst.w    d0
  221.     bne.s    wsend            ; if failed, return
  222.     bsr    w4stat            ; wait for status byte
  223.  
  224. .else    ;SCDMA
  225.                     ; hand shake the rest over the bus
  226.     movea.l    a0,a1            ; a1 -> buffer to write from
  227.     movea.l    #bSCSI,a2        ; a2 -> 5380
  228. .3:    bsr    setscstmout
  229.     bsr    w4req            ; wait for REQ to come
  230.     bmi.s    wsend            ; if timed out, returns
  231.     btst    #3,5*REGSTEP(a2)    ; still in data out phase?
  232.     beq    w4stat            ; no, go get status
  233.     move.b    (a1)+,(a2)        ; write the data byte
  234.     bsr    doack
  235.     bra.s    .3            ; do next byte
  236. .endif    ;SCDMA
  237. wsend:    rts
  238.  
  239.  
  240.  
  241. ;+
  242. ; sblkscsi() - set DMA pointer and count and send command block
  243. ;
  244. ; Passed:
  245. ;    d0.w = physical unit number
  246. ;    d1.l = transfer length (in bytes)
  247. ;    d2.w = command length (NCMD or LCMD)
  248. ;    a0.l = buffer address
  249. ;
  250. ; Returns:
  251. ;    d0.l =  0 if successful
  252. ;    d0.l = -1 if timeout
  253. ;-
  254.     .extern    _cmdblk
  255. sblkscsi:
  256.     movem.l    d1-d2/a0,-(sp)        ; preserve d1, d2 and a0
  257.     move.w    d0,-(sp)        ; physical unit #
  258.     bsr    selscsi            ; select the unit
  259.     addq.l    #2,sp            ; clean up stack
  260.     movem.l    (sp)+,d1-d2/a0        ; restore d1, d2 and a0
  261.     tst.w    d0            ; selection successful?
  262.     bmi.s    sbsend            ; if timed out, return
  263.                     ; else proceed
  264. .if    SCDMA
  265.     move.l    a0,d0            ; d0 = buffer address
  266.     movea.l    #bSDMAPTR,a1        ; a1 -> DMA address
  267.     movep.l    d0,(0,a1)        ; set DMA pointer
  268.  
  269.     movea.l    #bSDMACNT,a1        ; a1 -> DMA count
  270.     movep.l    d1,(0,a1)        ; set DMA count
  271. .endif    ;SCDMA
  272.  
  273.     move.b    #2,SCSITCR        ; assert C/D
  274.     move.b    #1,SCSIICR        ; assert data bus
  275.  
  276.     bsr    setscstmout        ; set up timeout for sending cmdblk
  277.     lea    _cmdblk,a1        ; a1 -> command block
  278.     subq.w    #1,d2            ; dbra likes one less
  279. .0:    move.b    (a1)+,d0        ; d0.b = byte to be sent
  280.     bsr    hshake            ; write that byte
  281.     tst.w    d0
  282.     bmi.s    sbsend            ; if timed-out, returns
  283.     dbra    d2,.0            ; until whole command block is sent
  284.     moveq    #0,d0            ; all operations successful
  285. sbsend: rts                ; heading home
  286.  
  287.  
  288. ;+
  289. ; BOOLEAN selscsi(SCSIUnit) 
  290. ; WORD SCSIUnit;
  291. ;-
  292. selscsi:
  293.     bsr    setscstmout        ; set up a short timeout
  294. .0:    btst    #6,SCSICR        ; STILL busy from last time?
  295.     beq.s    .1            ; if not, it's available
  296.     cmp.l    (a0),d1            ; timeout?
  297.     bhi.s    .0            ; not yet, wait some more
  298.     bra.s    .3            ; else, return error
  299.  
  300. .1:    move.b    #0,SCSITCR        ; data out phase
  301.     move.b    #0,SCSIISR        ; no interrupt from selection
  302.     move.b    #$0c,SCSIICR        ; assert BSY and SEL
  303. ; set dest SCSI IDs
  304.     clr.w    d0
  305.     move.w    4(sp),d1        ; get the SCSI unit desired
  306.     bset    d1,d0            ; set the appropriate bit
  307.     move.b    d0,SCSIODR        ; (real code would set ours too)
  308.  
  309.     move.b    #$0d,SCSIICR        ; assert BUSY, SEL and data bus
  310.     andi.b    #$FE,SCSIMR        ; clear arbitrate bit
  311.     andi.b    #$F7,SCSIICR        ; clear BUSY
  312.     nop                ; 2 deskew delays
  313.     nop
  314.  
  315.     bsr    setscstmout        ; set up for timeout
  316. .2:    btst    #6,SCSICR        ; wait for bus to be busy
  317.     bne.s    .4
  318.     cmp.l    (a0),d1
  319.     bhi.s    .2
  320.  
  321. .3:    moveq    #-1,d0            ; time out
  322.     bra.s    .5
  323.     
  324. .4:    clr.w    d0            ; selection successful
  325. .5:    move.b    #$0,SCSIICR        ; clear SEL and data bus assertion
  326.     rts
  327.  
  328.  
  329. *+
  330. * VOID resetscsi();
  331. *-
  332.     .globl    resetscsi
  333. resetscsi:
  334.     move.b    #$80,SCSIICR    ; assert RST
  335.     bsr    setscstmout    ; wait (at least) 250 ms
  336. .0:    cmp.l    (a0),d1
  337.     bhi.s    .0
  338.     move.b    #$00,SCSIICR
  339.     bsr    setscltmout    ; wait (at least) 1000 ms
  340. .1:    cmp.l    (a0),d1
  341.     bhi.s    .1
  342.     rts
  343.  
  344.  
  345. ;+
  346. ; w4int - wait for interrupts from 5380 or DMAC during DMA tranfers
  347. ;
  348. ; Passed:
  349. ;    d1.l = expiration time
  350. ;    a0.l = address of _hz_200
  351. ;
  352. ; Returns:
  353. ;    d0.l = returned status or timeout error
  354. ;
  355. ; Comments:
  356. ;    When 5380 is interrupted, it indicates a change of data to
  357. ; status phase (i.e., DMA is done), or ...
  358. ;    When DMAC is interrupted, it indicates either DMA count is
  359. ; zero, or there is an internal bus error.
  360. ;-
  361. w4int:    
  362. .0:    
  363. .if    VI
  364.     tst.b    phase_changed        ; phase changed?
  365. .else    ;VI
  366.     btst    #GPIP2SCSI,GPIP2    ; wait for 5380 to interrupt
  367. .endif    ;VI
  368.  
  369.     bne.s    .3            ; active HIGH
  370.     cmp.l    (a0),d1            ; time's up yet?
  371.     bls.s    .4            ; if not, wait some more
  372.  
  373. .if    VI
  374.     tst.b    dmac_int        ; DMAC interrupted?
  375.     bne.s    .1            ; if so, check out why
  376. .else    ;VI
  377.     btst    #5,GPIP2        ; or for DMAC to interrupt
  378.     beq.s    .1            ; active LOW
  379. .endif    ;VI
  380.  
  381.     cmp.l    (a0),d1            ; time's up yet?
  382.     bhi.s    .0            ; if not, wait some more
  383.                     ; timed-out
  384. .4:    bsr    resetscsi        ; reset the SCSI bus
  385.     moveq    #-1,d0            ; else, return timeout
  386.     bra.s    w4iend
  387.  
  388. .1:    move.w    SDMACTL,d0        ; get the DMAC status
  389.     andi.l    #$80,d0            ; check for bus err/ignore cntout ints
  390.  
  391. .if    VI
  392.     bne.s    .2            ; if bus error reset bus
  393.     sf    dmac_int        ; else clear dmac interrupt flag
  394.     bra.s    .0            ; and wait some more
  395. .else    ;VI
  396.     beq.s    .0            ; if fine, wait for interrupts again
  397. .endif    ;VI
  398.  
  399. .2:    move.w    d0,-(sp)        ; save the returned status
  400.     bsr    resetscsi        ; reset the SCSI bus
  401.     move.w    (sp)+,d0        ; d0 = return code
  402.  
  403. .if    VI
  404.     sf    dmac_int        ; clear dmac interrupt flag
  405. .endif    ;VI
  406.  
  407.     bra.s    w4iend            ; returns
  408. .3:    
  409. .if    VI
  410.     sf.b    phase_changed        ; clear phase change flag
  411.     move.b    SCSICR,d0        ; d0 = SCSI control register
  412.     andi.b    #$1c,d0            ; mask off irrelevant bits
  413.     cmpi.b    #$c,d0            ; data phase -> status phase?
  414.     bne.s    .0            ; if not, wait some more
  415. .endif    ;VI
  416.  
  417.     moveq    #0,d0            ; DMA is successful
  418.     move.b    SCSIREI,d1        ; clear potential interrupt
  419.     move.w    #DMADIS,SDMACTL        ; disable DMA
  420.     move.b    #0,SCSIMR        ; disable DMA mode
  421.     move.b    #0,SCSIICR        ; make sure data bus is not asserted
  422. w4iend:    rts
  423.  
  424.  
  425. ;+
  426. ; w4stat - wait for status byte and message byte.
  427. ;
  428. ; Returns:
  429. ;    d0.l = returned status or timeout error
  430. ;-
  431. w4stat:    bsr    setscstmout        ; set up time-out for REQ and ACK
  432.     move.b    #3,SCSITCR        ; status in phase
  433.     move.b    SCSIREI,d0        ; clear potential interrupt
  434.  
  435.     bsr    w4req            ; wait for status byte
  436.     bmi.s    w4send            ; if timed-out, returns
  437. gstat:    moveq    #0,d0            ; clear d0
  438.     move.b    SCSIDB,d0        ; get the status byte
  439.     move.l    d0,-(sp)        ; save the status byte
  440.     bsr    setscstmout        ; set up time-out for REQ and ACK
  441.     bsr    doack            ; signal that status byte is here
  442.     tst.w    d0            ; timed-out?
  443.     beq.s    .1            ; if not, wait for message byte
  444.  
  445. .0:    addq.l    #4,sp            ; else clean up stack
  446.     bra.s    w4send            ; and return
  447.  
  448. .1:    bsr    setscstmout        ; set up timeout for REQ and ACK
  449.     bsr    w4req            ; wait for message byte
  450.     bmi.s    .0            ; if timed-out, returns
  451.  
  452.     move.b    SCSIDB,d0        ; get and ignore message byte
  453.     bsr    doack            ; signal that message byte is here
  454.     tst.w    d0            ; timed-out?
  455.     bmi.s    .0            ; if so, return timeout
  456.  
  457. .if    DEBUG
  458.     move.l    #_hz_200,a0        ; For debugging SEA177N - 
  459.     moveq    #4,d1            ;   add a delay after receiving 
  460.     add.l    (a0),d1            ;   message byte
  461. .2:    cmp.l    (a0),d1
  462.     bhi.s    .2
  463. .endif    ;DEBUG
  464.  
  465.     move.l    (sp)+,d0        ; recall the status byte
  466. w4send:    rts
  467.  
  468.  
  469. ;+
  470. ; w4req() - wait for REQ to come
  471. ;
  472. ; Passed:
  473. ;    d1.l = expiration time
  474. ;    a0.l = address of _hz_200
  475. ;
  476. ; Returns:
  477. ;     0 - if successful
  478. ;    -1 - times out
  479. ;-
  480. w4req:
  481. .0:    btst    #5,SCSICR        ; waiting for REQ to come
  482.     bne.s    .1            ; if REQ comes, done
  483.     cmp.l    (a0),d1            ; time's up?
  484.     bhi.s    .0            ; if not, wait some more
  485.     moveq    #-1,d0            ; else, returns timed out
  486.     bra.s    w4rend
  487. .1:    moveq    #0,d0            ; returns successful
  488. w4rend:    rts
  489.  
  490.  
  491. ;+
  492. ; doack() - assert ACK
  493. ;
  494. ; Passed:
  495. ;    d1.l = expiration time
  496. ;    a0.l = address of _hz_200
  497. ;
  498. ; Returns:
  499. ;     0 - if successful
  500. ;    -1 - times out
  501. ;-
  502. doack:    ori.b    #$11,SCSIICR        ; assert ACK (and data bus)
  503. .0:    btst    #5,SCSICR        ; wait for REQ to go away
  504.     beq.s    .1            ; if REQ goes away, done
  505.     cmp.l    (a0),d1            ; time's up?
  506.     bhi.s    .0            ; if not, wait some more
  507.     moveq    #-1,d0            ; else returns timed out
  508.     bra.s    doaend
  509. .1:    moveq    #0,d0            ; returns successful
  510. doaend:    andi.b    #$ef,SCSIICR        ; clear ACK
  511.     rts
  512.  
  513.  
  514. ;+
  515. ; hshake() - hand shake a byte over to the controller
  516. ;
  517. ; Passed:
  518. ;    d0.b = byte to be handed over
  519. ;    d1.l = expiration time
  520. ;    a0.l = address of _hz_200
  521. ;
  522. ; Returns:
  523. ;    Whatever w4req() or doack() returns, which is:
  524. ;         0 - if successful
  525. ;        -1 - times out
  526. ;-
  527. hshake:    move.w    d0,-(sp)        ; preserve d0.w
  528.     bsr    w4req            ; wait for REQ to come
  529.     bmi.s    hsend            ; if timed out, returns
  530.     move.b    1(sp),SCSIDB        ; write a byte out to data bus
  531.     bsr    doack            ; assert ACK
  532. hsend:    addq.l    #2,sp            ; clean up stack
  533.     rts
  534.  
  535.  
  536. ;+
  537. ; setscstmout - set up a timeout count for the SCSI for SCSTMOUT long
  538. ;
  539. ; Returns:
  540. ;    a0.l = address of _hz_200 clock
  541. ;    d1.l = expiration time
  542. ;-
  543.  
  544. .if    DRIVER                ; to be included in driver
  545.     .extern    scstmout
  546. .endif    ;DRIVER
  547.  
  548. setscstmout:
  549.     movea.l    #_hz_200,a0        ; a0 -> 200 hz clock
  550.     move.l    scstmout,d1        ; d0 = scstmout _hz_200 clicks
  551.     add.l    (a0),d1            ; d0 = curr time + # clicks to wait
  552.     rts
  553.  
  554.  
  555. ;+
  556. ; setscltmout - set up a timeout count for the SCSI for SCLTMOUT long
  557. ;
  558. ; Returns:
  559. ;    a0.l = address of _hz_200 clock
  560. ;    d1.l = expiration time
  561. ;-
  562.  
  563. .if    DRIVER                ; to be included in driver
  564.     .extern    scltmout
  565. .endif    ;DRIVER
  566.  
  567. setscltmout:
  568.     movea.l    #_hz_200,a0        ; a0 -> 200 hz clock
  569.     move.l    scltmout,d1        ; d0 = scltmout _hz_200 clicks
  570.     add.l    (a0),d1            ; d0 = curr time + # clicks to wait
  571.     rts
  572.  
  573.  
  574. ;+
  575. ; setscxltmout - set up a timeout count for the SCSI for SCXLTMOUT long
  576. ;
  577. ; Returns:
  578. ;    a0.l = address of _hz_200 clock
  579. ;    d1.l = expiration time
  580. ;-
  581.  
  582. .if    DRIVER                ; to be included in driver
  583.     .extern    scxltmout
  584. .endif    ;DRIVER
  585.  
  586. setscxltmout:
  587.     movea.l    #_hz_200,a0        ; a0 -> 200 hz clock
  588.     move.l    scxltmout,d1        ; d0 = scltmout _hz_200 clicks
  589.     add.l    (a0),d1            ; d0 = curr time + # clicks to wait
  590.     rts
  591.  
  592.  
  593.  
  594. .if    !DRIVER                ; not to be included in driver
  595.  
  596. ;+
  597. ; fmtscsi() - format a SCSI unit
  598. ;
  599. ;    d0.w = physical unit number
  600. ;    d1.l = transfer length (in bytes)
  601. ;    d2.w = command length (NCMD or LCMD)
  602. ;    a0.l = buffer address
  603. ;-
  604.     .globl    _fmtscsi
  605. _fmtscsi:
  606.     andi.w    #7,d0            ; mask off the flags to get unit num
  607.     bsr    sblkscsi        ; send command block
  608.     bpl.s    .0            ; if successful, wait for status byte
  609.     rts                ; else return
  610. .0:    move.b    #3,SCSITCR        ; status in phase
  611.     move.b    SCSIREI,d0        ; clear potential interrupt
  612. .1:    btst    #5,SCSICR        ; wait forever for REQ to 
  613.  
  614.  
  615. .if    DEBUG
  616.  
  617.     bne.s    .3            ; For debugging purpose - 
  618.     move.l    #_hz_200,a0        ;    add a delay in this "tight" 
  619.     moveq    #2,d1            ;    loop to slow down SCSI chip 
  620.     add.l    (a0),d1            ;    accessing.
  621. .2:    cmp.l    (a0),d1
  622.     bhi.s    .2
  623.     bra.s    .1
  624.  
  625. .else    ;DEBUG
  626.  
  627.     beq.s    .1            ;   come
  628.  
  629. .endif    ;DEBUG
  630.  
  631. .3:    bra    gstat            ; when REQ comes, get status byte
  632.  
  633. .endif    ;!DRIVER
  634.  
  635.  
  636. .if    VI
  637. ;+
  638. ; scsi_isr - interrupt service routine for SCSI phase changes
  639. ;-
  640.     .globl    scsi_isr
  641. scsi_isr:
  642.     movem.l    d0-d1,-(sp)        ; save d0 and d1
  643.     move.b    SCSIDSR,d0        ; read DMA status register
  644.     move.b    d0,d1            ; d0 and d1 contains DMA status
  645.     andi.b    #$10,d0            ; interrupt coming from IRQ
  646.     beq.s    scsiend            ; if not, not interested
  647.     andi.b    #$2c,d1            ; else mask off irrelevant bits
  648.     cmpi.b    #$1f,d1            ; if status > 0x1f
  649.     bhi.s    scsiend            ;   ignore parity error interrupt
  650.     btst.l    #$3,d1            ; phase match bit cleared?
  651.     bne.s    scsiend            ; if not, not interested
  652.                     ; else it's a phase mismatch interrupt
  653.     st    phase_changed        ; set flag to indicate phase changes
  654. scsiend:
  655.     movem.l    (sp)+,d0-d1        ; restore d0 and d1
  656.     move.b    #$7f,ISRA2        ; clear GPIP2SCSI in-service bit
  657.     rte
  658.  
  659.  
  660.  
  661. ;+
  662. ; dmac_isr - interrupt service routine for DMAC
  663. ;    It means we are either a cntout zero or internal bus error.
  664. ;-
  665.     .globl    dmac_isr
  666. dmac_isr:
  667.     st    dmac_int        ; indicate DMAC was interrupted
  668.     move.b    #$7f,ISRB2        ; clear GPIP25 in-service bit 
  669.     rte
  670.  
  671. .endif    ;VI
  672.  
  673.